package com.srp.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.*;
import java.nio.charset.StandardCharsets;

@Slf4j
public class FileUtils {

    private static final String SLASH_CHARACTER = "/";

    public static void uploadFile(byte[] file, String filePath, String fileName) throws IOException {

        File targetFile = new File(filePath);
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }
        FileOutputStream out = new FileOutputStream(filePath + fileName);
        out.write(file);
        out.flush();
        out.close();
    }

    /**
     * 检查文件夹是否存在，否则创建文件夹
     *
     * @param path the path
     * @return returns the path
     */
    public static String checkDir(String path) {

        String checkPath = path;

        if (!checkPath.endsWith(SLASH_CHARACTER)) {
            checkPath = checkPath + SLASH_CHARACTER;
        }

        File checkDir = new File(checkPath);
        if (!checkDir.exists()) {
            boolean success = checkDir.mkdirs();
            if (!success) {
                log.error("checkDir.mkdirs");
            }
        }
        return checkPath;
    }

    /**
     * 从路径中读取文件内容
     *
     * @param path 文件路径
     * @return []byte 返回字节流
     */
    public static byte[] readFileByPath(String path) {

        log.info("get data form [{}]", path);
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(path);
            byte[] buff = new byte[fis.available()];
            int size = fis.read(buff);
            if (size > 0) {
                return buff;
            } else {
                log.warn("readFileByPath's file is empty.");
                return new byte[0];
            }
        } catch (FileNotFoundException e) {
            log.error("readFileByPath error", e);
        } catch (IOException e) {
            log.error("readFileByPath error", e);
        } finally {
            close(fis);
        }
        return new byte[0];
    }


    /**
     * 保存路径对应的文件内容
     *
     * @param filePath 文件路径
     * @param data     保存的数据
     * @return return  保存文件的绝对路径
     */
    public static String saveFileToPath(String filePath, byte[] data) {

        log.info("save data in to [{}]", filePath);
        FileOutputStream fo = null;
        try {
            File file = new File(filePath);
            fo = new FileOutputStream(file);
            fo.write(data);
            return file.getAbsolutePath();
        } catch (IOException e) {
            log.error("writer file exception", e);
        } finally {
            close(fo);
        }
        return StringUtils.EMPTY;
    }

    /**
     *  Base64加密并保存路径对应的文件内容
     *
     * @param filePath 文件路径
     * @param data     保存的数据
     * @return return  保存文件的绝对路径
     */
    public static String saveEncodedFileToPath(String filePath, byte[] data) {

        BASE64Encoder base64Encoder = new BASE64Encoder();
        String dataEncoded = base64Encoder.encode(data);
        String retString = saveFileToPath(filePath,dataEncoded.getBytes());
        return retString;
    }

    /**
     * 从路径中读取文件内容并Base64解码
     *
     * @param path 文件路径
     * @return []byte 返回字符串
     */
    public static String readFileAndDecode(String path) {

        BASE64Decoder base64Decoder = new BASE64Decoder();
        byte[] data = readFileByPath(path);
        byte[] bytes = new byte[0];
        try {
            bytes = base64Decoder.decodeBuffer(new String(data));
        } catch (Exception e) {
            log.error("readFileAndDecode filed", e);
        }
        return new String(bytes, StandardCharsets.UTF_8);
    }

    /**
     * close the input stream
     *
     * @param is input stream
     */
    public static void close(InputStream is) {
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
                log.error("io close exception.", e);
            }
        }
    }

    /**
     * close the output stream
     *
     * @param os output stream
     */
    public static void close(OutputStream os) {
        if (os != null) {
            try {
                os.close();
            } catch (IOException e) {
                log.error("io close exception.", e);
            }
        }
    }

    /**
     * copy the source file to target file, if the
     *
     * @param srcFile    soruce file
     * @param targetFile target file
     */
    public static void copy(File srcFile, File targetFile) {
        //创建输入输出流
        InputStream in = null;
        OutputStream out = null;
        try {
            in = new FileInputStream(srcFile);
            out = new FileOutputStream(targetFile);
            byte[] bytes = new byte[1024];
            int len = -1;
            while ((len = in.read(bytes)) != -1) {
                out.write(bytes, 0, len);
            }
            out.flush();
        } catch (FileNotFoundException e) {
            log.error("the file can not found.", e);
        } catch (IOException e) {
            log.error("copy file exception.", e);
        } finally {
            close(in);
            close(out);
        }
    }

}
